home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 422_02 / dosutil / diff.c < prev    next >
C/C++ Source or Header  |  1994-03-20  |  5KB  |  224 lines

  1. /*
  2.  * Displays differences between two ASCII files
  3.  *
  4.  * Options:
  5.  *    -d        = Inhibit display of differences
  6.  *    -l        = Inhibit display of line numbers
  7.  *    r=num    = Minimum # lines to re-syncronize
  8.  *
  9.  * Copyright 1988-1994 Dave Dunfield
  10.  * All rights reserved.
  11.  *
  12.  * Permission granted for personal (non-commercial) use only.
  13.  *
  14.  * Compile command: cc diff -fop
  15.  */
  16. #include <stdio.h>
  17.  
  18. #define    LINE_SIZE    100        /* maximum size of input lines */
  19. #define    MAX_DIFF    200        /* maximum number of different lines */
  20.  
  21. char ft1[MAX_DIFF][LINE_SIZE], ft2[MAX_DIFF][LINE_SIZE];
  22.  
  23. unsigned r1 = 0, r2 = 0, w1 = 0, w2 = 0, l1, l2;
  24. unsigned resync = 2, diffs = 0;
  25.  
  26. char diff = -1, line = -1;
  27.  
  28. char *fn1, *fn2;
  29. FILE *fp1, *fp2;
  30.  
  31. /*
  32.  * Main program, compare files
  33.  */
  34. main(argc, argv)
  35.     int argc;
  36.     char *argv[];
  37. {
  38.     char *ptr;
  39.  
  40.     l2 = 0;
  41.     for(l1 = 1; l1 < argc; ++l1) {
  42.         ptr = argv[l1];
  43.         switch((tolower(*ptr++) << 8) | tolower(*ptr++)) {
  44.             case 'r=' :            /* minimum # lines to resync */
  45.                 resync = get_num(ptr);
  46.                 break;
  47.             case '-d' :            /* inhibit display of differences */
  48.                 diff = 0;
  49.                 break;
  50.             case '-l' :            /* inhibit display of line numbers */
  51.                 line = 0;
  52.                 break;
  53.             default:            /* filename to compare */
  54.                 if(!(fp2 = fopen(fn2 = argv[l1], "r"))) {
  55.                     fprintf(stderr, "%s: Unable to open\n", fn2);
  56.                     exit(-1); }
  57.                 if(!l2++) {
  58.                     fn1 = fn2;
  59.                     fp1 = fp2; } } }
  60.  
  61.     if(l2 != 2) {
  62.         fputs("\nUse: diff <file1> <file2> [-d -l r=#lines]\n\nCopyright 1988-1994 Dave Dunfield\nAll rights reserved.\n", stderr);
  63.         exit(-1); }
  64.  
  65.     l1 = l2 = 1;
  66.     for(;;) {
  67.         fill_buffer();
  68.         if((r1 == w1) || (r2 == w2)) {
  69.             show_changed(w1, w2);
  70.             if(diffs)
  71.                 fprintf(stdout,"%u differences.\n", diffs);
  72.             else
  73.                 fprintf(stdout,"Files match exactly.\n");
  74.             exit(diffs); }
  75.         if(equal(ft1[r1], ft2[r2])) {
  76.             r1 = (r1 + 1) % MAX_DIFF;
  77.             r2 = (r2 + 1) % MAX_DIFF;
  78.             ++l1; ++l2;
  79.             continue; }
  80.         scan_buffer(); }
  81. }
  82.  
  83. /*
  84.  * Fill up the buffer with lines from the input file
  85.  */
  86. fill_buffer()
  87. {
  88.     register int j1, j2;
  89.  
  90.     while((j1 = (w1 + 1) % MAX_DIFF) != r1) {
  91.         if(!fgets(ft1[w1], LINE_SIZE, fp1))
  92.             break;
  93.         w1 = j1; }
  94.     while((j2 = (w2 + 1) % MAX_DIFF) != r2) {
  95.         if(!fgets(ft2[w2], LINE_SIZE, fp2))
  96.             break;
  97.         w2 = j2; }
  98. }
  99.  
  100. /*
  101.  * Scan the buffer looking for a pattern
  102.  */
  103. scan_buffer()
  104. {
  105.     int i, i1, i2, j1, j2;
  106.     char flag;
  107.  
  108.     i1 = r1;
  109.     i2 = r2;
  110.     fill_buffer();
  111.     do {        /* scan with this portion */
  112.         j1 = i1;
  113.         j2 = i2;
  114.         do {
  115.             flag = 0;
  116.             if(j2 != w2) {        /* we can check this one */
  117.                 flag = -1;
  118.                 if(equal(ft1[i1], ft2[j2]) && (i=test_next(i1, j2))) {
  119.                     show_changed(i1, j2);
  120.                     r1 = (r1 + i) % MAX_DIFF;
  121.                     r2 = (r2 + i) % MAX_DIFF;
  122.                     l1 += i; l2 += i;
  123.                     return; }
  124.                 j2 = (j2 + 1) % MAX_DIFF; }
  125.             if(j1 != w1) {        /* we can check this one */
  126.                 flag = -1;
  127.                 if(equal(ft1[j1], ft2[i2]) && (i=test_next(j1, i2))) {
  128.                     show_changed(j1, i2);
  129.                     r1 = (r1 + i) % MAX_DIFF;
  130.                     r2 = (r2 + i) % MAX_DIFF;
  131.                     l1 += i; l2 += i;
  132.                     return; }
  133.                 j1 = (j1 + 1) % MAX_DIFF; } }
  134.         while(flag);
  135.         if(i1 != w1) {        /* More lines in buffer */
  136.             i1 = (i1 + 1) % MAX_DIFF;
  137.             flag = -1; }
  138.         if(i2 != w2) {        /* More lines in buffer */
  139.             i2 = (i2 + 1) % MAX_DIFF;
  140.             flag = -1; } }
  141.     while(flag);
  142.  
  143. /* Cannot accept any more data into buffers, check for overflow */
  144.     if((((w1 + 1) % MAX_DIFF) == r1) || (((w2 + 1) % MAX_DIFF) == r2)) {
  145.         fprintf(stdout,"Differences to great at  %u < > %u\n", l1, l2);
  146.         exit(-1); }
  147. /* Buffers not full, must be end of file */
  148.     show_changed(w1, w2);
  149. }
  150.  
  151. /*
  152.  * Test that the next "resync" entries match
  153.  */
  154. test_next(i1, i2)
  155.     unsigned i1, i2;
  156. {
  157.     int i;
  158.  
  159.     for(i=1; i < resync; ++i) {
  160.         i1 = (i1 + 1) % MAX_DIFF;
  161.         i2 = (i2 + 1) % MAX_DIFF;
  162.         if((i1 == w1) || (i2 == w2))
  163.             return i;
  164.         if(!equal(ft1[i1], ft2[i2]))
  165.             return 0; }
  166.     return i;
  167. }
  168.  
  169. /*
  170.  * Display the changed lines & reset read pointers
  171.  */
  172. show_changed(i1, i2)
  173.     unsigned i1, i2;
  174. {
  175.     if((r1 != i1) || (r2 != i2)) {
  176.         ++diffs;
  177.         if(line)
  178.             fprintf(stdout,"*** %s(%u) < > %s(%u) ***\n", fn1, l1, fn2, l2);
  179.         while(r1 != i1) {
  180.             ++l1;
  181.             if(diff)
  182.                 fprintf(stdout,"<%s\n", ft1[r1]);
  183.             r1 = (r1 + 1) % MAX_DIFF; }
  184.         while(r2 != i2) {
  185.             ++l2;
  186.             if(diff)
  187.                 fprintf(stdout,">%s\n", ft2[r2]);
  188.             r2 = (r2 + 1) % MAX_DIFF; } }
  189. }
  190.  
  191. /*
  192.  * Get a decimal number from the command line
  193.  */
  194. get_num(string)
  195.     char *string;
  196. {
  197.     register unsigned value;
  198.     register char chr;
  199.  
  200.     value = 0;
  201.     while(isdigit(chr = *string++))
  202.         value = (value * 10) + (chr - '0');
  203.  
  204.     if(chr) {
  205.         fputs("DIFF: Invalid number\n", stderr);
  206.         exit(-1); }
  207.  
  208.     return    value;
  209. }
  210.  
  211. /*
  212.  * Test for two strings equal
  213.  */
  214. equal(str1, str2)
  215.     char *str1, *str2;
  216. {
  217.     register char c;
  218.  
  219.     while((c = *str1++) == *str2++) {
  220.         if(!c)
  221.             return 1; }
  222.     return 0;
  223. }
  224.